﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;

namespace AAPT_Patch
{
    class Program
    {
        static void Main(string[] args)
        {
            // Rebuild command line arguments
            Process aapt = new Process();
            StringBuilder cmdLineBuilder = new StringBuilder();
            for (int i = 0; i < args.Length; i++)
            {
                if (i > 0)
                    cmdLineBuilder.Append(' ');
                bool hasSpaces = (args[i].IndexOf(' ') >= 0);
                if (hasSpaces == true)
                    cmdLineBuilder.Append('"');
                cmdLineBuilder.Append(args[i]);
                if (hasSpaces == true)
                    cmdLineBuilder.Append('"');
            }

            // Run original AAPT
            aapt.StartInfo.FileName = "aapt-original.exe";
            aapt.StartInfo.CreateNoWindow = true;
            aapt.StartInfo.UseShellExecute = false;
            aapt.StartInfo.RedirectStandardOutput = true;
            aapt.StartInfo.Arguments = cmdLineBuilder.ToString();

            aapt.Start();

            string standardOutput = aapt.StandardOutput.ReadToEnd();

            aapt.WaitForExit();

            Console.Out.Write(standardOutput);

            // Post processing 
            // If the AAPT flag was on 'crunch', verify that the output files are smaller than the input files. If not,
            // overwrite the output files with the input files. 
            // Bottom line, make sure that InputFile.Length >= OutputFile.Length
            if ((args.Length > 0) && ("crunch".Equals(args[0])))
            {
                string inputFolder = null;
                string outputFolder = null;

                for (int i = 0; i < args.Length - 1; i++)
                {
                    if ("-S".Equals(args[i]))
                        inputFolder = args[i + 1];
                    if ("-C".Equals(args[i]))
                        outputFolder = args[i + 1];
                }

                if (inputFolder == null)
                    Console.WriteLine("Failed to find input folder");
                else if (outputFolder == null)
                    Console.WriteLine("Failed to find output folder");
                else
                    TraverseCrunchedFolders(inputFolder, outputFolder, null);
            }
        }

        private static void TraverseCrunchedFolders(string inputFolder, string outputFolder, string subdirectory)
        {
            string currentInputFolder;
            string currentOutputFolder;
            if (subdirectory == null)
            {
                currentInputFolder = inputFolder;
                currentOutputFolder = outputFolder;
            }
            else
            {
                currentInputFolder = Path.Combine(inputFolder, subdirectory);
                currentOutputFolder = Path.Combine(outputFolder, subdirectory);
            }

            // Verify InputFile.Length >= OutputFile.Length
            string[] files = Directory.GetFiles(currentInputFolder);
            foreach (string file in files)
            {
                FileInfo fileInfo = new FileInfo(file);
                string outputFile = Path.Combine(currentOutputFolder, fileInfo.Name);
                if (File.Exists(outputFile) == false)
                    continue;
                FileInfo outputFileInfo = new FileInfo(outputFile);
                if (outputFileInfo.Length <= fileInfo.Length)
                    continue;

                File.Delete(outputFile);
                File.Copy(file, outputFile);
            }

            // Process sub folders
            string[] subFolders = Directory.GetDirectories(currentInputFolder);
            foreach (string subFolder in subFolders)
            {
                DirectoryInfo dirInfo = new DirectoryInfo(subFolder);
                if (subdirectory != null)
                    TraverseCrunchedFolders(inputFolder, outputFolder, Path.Combine(subdirectory, dirInfo.Name));
                else
                    TraverseCrunchedFolders(inputFolder, outputFolder, dirInfo.Name);
            }
        }
    }
}
